﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// IM2 = imcomplement(IM) computes the complement of the image IM.
    /// IM can be a binary, grayscale, or RGB image. IM2 has the same class and size as IM.
    /// In the complement of a binary image, zeros become ones and ones become zeros; 
    /// black and white are reversed. In the complement of an intensity or RGB image, 
    /// each pixel value is subtracted from the maximum pixel value supported by the class 
    /// (or 1.0 for double-precision images) and the difference is used as the pixel value in the output image.
    /// In the output image, dark areas become lighter and light areas become darker.
    /// 
    /// If IM is an grayscale or RGB image of class double, you can use the expression 1-IM instead of this function.
    /// If IM is a binary image, you can use the expression ~IM instead of this function.
    /// 
    /// Examples
    /// Create the complement of a uint8 array.
    /// 
    /// X = uint8([ 255 10 75; 44 225 100]);
    /// X2 = imcomplement(X)
    /// X2 =
    /// 0   245   180
    /// 211    30   155
    /// 
    /// Reverse black and white in a binary image.
    /// bw = imread('text.png');
    /// bw2 = imcomplement(bw);
    /// subplot(1,2,1),imshow(bw)
    /// subplot(1,2,2),imshow(bw2)
    /// Create the complement of an intensity image.
    /// I = imread('glass.png');
    /// J = imcomplement(I);
    /// imshow(I), figure, imshow(J)    
    /// </summary>
    public class imcomplement : BaseImageFilter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="imcomplement"/> class.
        /// </summary>
        public imcomplement()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="imcomplement"/> class.
        /// </summary>
        /// <param name="_imcomplement">The _imcomplement.</param>
        internal imcomplement(imcomplement _imcomplement)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;

            int y = 0;
            int x = 0;

            Color color = Color.Transparent;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap.GetPixel(x, y);
                    int nR = 255 - color.R;
                    int nG = 255 - color.G;
                    int nB = 255 - color.B;

                    _bitmap.SetPixel(x, y, Color.FromArgb(Math.Abs(color.R-nR), Math.Abs(color.G-nG), Math.Abs(color.B-nB)));
                }
            }

            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new imcomplement(this);
        }
    }
}
